<!DOCTYPE html>
<html>
    <head>
        <script src="/w3c/resources/testharness.js"></script>
        <script src="/w3c/resources/testharnessreport.js"></script>
        <script src="mediasource-util.js"></script>
    </head>
    <body>
        <script>
            function verifyTrackProperties(trackType, track, expectedTrackInfo) {
                assert_equals(track.kind, expectedTrackInfo.kind, trackType + ".kind");
                assert_equals(track.label, expectedTrackInfo.label, trackType + ".label");
                assert_equals(track.language, expectedTrackInfo.language, trackType + ".language");
            }

            function loadMediaAndVerifyAddedTracks(test, mediaElement, segmentInfo, sourceBuffer, mediaData, expectedAudioTrackInfo, expectedVideoTrackInfo, successCallback)
            {
                var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
                test.expectEvent(sourceBuffer.audioTracks, "addtrack", "sourceBuffer.audioTracks addtrack event");
                test.expectEvent(sourceBuffer.videoTracks, "addtrack", "sourceBuffer.videoTracks addtrack event");
                test.expectEvent(mediaElement.audioTracks, "addtrack", "mediaElement.audioTracks addtrack event");
                test.expectEvent(mediaElement.videoTracks, "addtrack", "mediaElement.videoTracks addtrack event");
                test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata done.");
                test.expectEvent(sourceBuffer, "updateend", "initSegment append ended.");
                sourceBuffer.appendBuffer(initSegment);
                test.waitForExpectedEvents(function()
                {
                    assert_equals(sourceBuffer.audioTracks.length, 1, "audioTracks.length");
                    verifyTrackProperties("audio", sourceBuffer.audioTracks[0], expectedAudioTrackInfo);
                    assert_equals(sourceBuffer.audioTracks[0].sourceBuffer, sourceBuffer, "audioTrack.sourceBuffer");
                    // The first audio track is enabled by default.
                    assert_true(sourceBuffer.audioTracks[0].enabled, "sourceBuffer.audioTracks[0].enabled");

                    assert_equals(sourceBuffer.videoTracks.length, 1, "videoTracks.length");
                    verifyTrackProperties("video", sourceBuffer.videoTracks[0], expectedVideoTrackInfo);
                    assert_equals(sourceBuffer.videoTracks[0].sourceBuffer, sourceBuffer, "videoTrack.sourceBuffer");
                    // The first video track is selected by default.
                    assert_true(sourceBuffer.videoTracks[0].selected, "sourceBuffer.videoTracks[0].selected");

                    assert_not_equals(sourceBuffer.audioTracks[0].id, sourceBuffer.videoTracks[0].id, "track ids must be unique");

                    assert_equals(mediaElement.videoTracks.length, 1, "videoTracks.length");
                    assert_equals(mediaElement.videoTracks[0], sourceBuffer.videoTracks[0], "mediaElement.videoTrack == sourceBuffer.videoTrack");

                    assert_equals(mediaElement.audioTracks.length, 1, "audioTracks.length");
                    assert_equals(mediaElement.audioTracks[0], sourceBuffer.audioTracks[0], "mediaElement.audioTrack == sourceBuffer.audioTrack");

                    successCallback();
                });
            }

            mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
            {
                var expectedAudioTrackInfo = { kind: "main", label: "", language: "" };
                var expectedVideoTrackInfo = { kind: "main", label: "", language: "" };

                loadMediaAndVerifyAddedTracks(test, mediaElement, segmentInfo, sourceBuffer, mediaData, expectedAudioTrackInfo, expectedVideoTrackInfo, test.step_func(function ()
                {
                    // Now append the same exact init segment again. This should succeed, but no new tracks should
                    // be added to the SourceBuffer or MediaElement.
                    test.failOnEvent(sourceBuffer.audioTracks, "addtrack", "Unexpected addtrack event on sourceBuffer.audioTracks for second init segment");
                    test.failOnEvent(sourceBuffer.videoTracks, "addtrack", "Unexpected addtrack event on sourceBuffer.videoTracks for second init segment");
                    test.failOnEvent(mediaElement.audioTracks, "addtrack", "Unexpected addtrack event on mediaElement.audioTracks for second init segment");
                    test.failOnEvent(mediaElement.videoTracks, "addtrack", "Unexpected addtrack event on mediaElement.videoTracks for second init segment");

                    test.expectEvent(sourceBuffer, "updateend", "InitSegment append ended.");
                    var initSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.init);
                    sourceBuffer.appendBuffer(initSegment);
                    test.waitForExpectedEvents(function()
                    {
                        assert_equals(mediaElement.audioTracks.length, 1, "mediaElement.audioTracks.length");
                        assert_equals(mediaElement.videoTracks.length, 1, "mediaElement.videoTracks.length");
                        assert_equals(sourceBuffer.audioTracks.length, 1, "sourceBuffer.audioTracks.length");
                        assert_equals(sourceBuffer.videoTracks.length, 1, "sourceBuffer.videoTracks.length");
                        test.done();
                    });
                }));
            }, "Same init segment appended twice");

            mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
            {
                var originalTrackDefaults = [
                    new TrackDefault("audio", "audio-language", "audio-label", ["main"], "2"),
                    new TrackDefault("video", "video-language", "video-label", ["main"], "1")
                ];
                var trackDefaultList = new TrackDefaultList(originalTrackDefaults.slice());
                sourceBuffer.trackDefaults = trackDefaultList;

                var expectedAudioTrackInfo = { kind: "main", label: "audio-label", language: "audio-language" };
                var expectedVideoTrackInfo = { kind: "main", label: "video-label", language: "video-language" };

                loadMediaAndVerifyAddedTracks(test, mediaElement, segmentInfo, sourceBuffer, mediaData, expectedAudioTrackInfo, expectedVideoTrackInfo, test.step_func_done());
            }, "Track defaults processing in the init segment algorithm (explicit bytestream ids)");

            mediasource_testafterdataloaded(function(test, mediaElement, mediaSource, segmentInfo, sourceBuffer, mediaData)
            {
                var originalTrackDefaults = [
                    new TrackDefault("audio", "audio-language", "audio-label", ["main"], ""),
                    new TrackDefault("video", "video-language", "video-label", ["main"], "")
                ];
                var trackDefaultList = new TrackDefaultList(originalTrackDefaults.slice());
                sourceBuffer.trackDefaults = trackDefaultList;

                var expectedAudioTrackInfo = { kind: "main", label: "audio-label", language: "audio-language" };
                var expectedVideoTrackInfo = { kind: "main", label: "video-label", language: "video-language" };

                loadMediaAndVerifyAddedTracks(test, mediaElement, segmentInfo, sourceBuffer, mediaData, expectedAudioTrackInfo, expectedVideoTrackInfo, test.step_func_done());
            }, "Track defaults processing in the init segment algorithm (no bytestream ids)");

            mediasource_test(function(test, mediaElement, mediaSource)
            {
                var subType = MediaSourceUtil.getSubType(MediaSourceUtil.AUDIO_VIDEO_TYPE);
                var manifestFilenameA = subType + '/test-a-128k-44100Hz-1ch-manifest.json';
                var manifestFilenameV = subType + '/test-v-128k-320x240-30fps-10kfr-manifest.json';

                MediaSourceUtil.fetchManifestAndData(test, manifestFilenameA, function(typeA, dataA)
                {
                    MediaSourceUtil.fetchManifestAndData(test, manifestFilenameV, function(typeV, dataV)
                    {
                        var sourceBufferA = mediaSource.addSourceBuffer(typeA);
                        var sourceBufferV = mediaSource.addSourceBuffer(typeV);
                        sourceBufferA.trackDefaults = new TrackDefaultList([new TrackDefault("audio", "", "audio-label-for-track-bsid1", ["main"], "1")]);
                        sourceBufferV.trackDefaults = new TrackDefaultList([new TrackDefault("video", "", "video-label-for-track-bsid1", ["main"], "1")]);

                        test.expectEvent(mediaElement.audioTracks, "addtrack", "mediaElement.audioTracks addtrack event");
                        test.expectEvent(mediaElement, "loadedmetadata", "loadedmetadata done.");
                        test.expectEvent(sourceBufferA, "updateend", "initSegment append ended.");
                        test.expectEvent(sourceBufferV, "updateend", "initSegment append ended.");
                        sourceBufferA.appendBuffer(dataA);
                        sourceBufferV.appendBuffer(dataV);
                        test.waitForExpectedEvents(function()
                        {
                            assert_equals(mediaElement.audioTracks.length, 1, "mediaElement.audioTracks.length");
                            assert_equals(mediaElement.videoTracks.length, 1, "mediaElement.audioTracks.length");
                            assert_equals(sourceBufferA.audioTracks.length, 1, "sourceBufferA.audioTracks.length");
                            assert_equals(sourceBufferA.videoTracks.length, 0, "sourceBufferA.videoTracks.length");
                            assert_equals(sourceBufferV.audioTracks.length, 0, "sourceBufferV.audioTracks.length");
                            assert_equals(sourceBufferV.videoTracks.length, 1, "sourceBufferV.videoTracks.length");
                            // Verify that audio track bytestream id == video track bytestream id == "1"
                            assert_equals(sourceBufferA.audioTracks[0].label, "audio-label-for-track-bsid1", "audio track bytestream id is 1");
                            assert_equals(sourceBufferV.videoTracks[0].label, "video-label-for-track-bsid1", "video track bytestream id is 1");
                            // Track ids generated for media tracks must be unique, even though the tracks have identical bytestream ids.
                            assert_not_equals(sourceBufferA.audioTracks[0].id, sourceBufferV.videoTracks[0].id, "track ids must be unique");
                            test.done();
                        });
                    });
                });
            }, "Two source buffers with clashing bytestream track ids");

        </script>
    </body>
</html>
